#include "staticfunctions.h"
#include "pathdialog.h"
#include "dcolordialog.h"

PathDialog::PathDialog(QWidget *parent) :
  QDialog(parent)
{
  ui.setupUi(this);

  m_pointDialog = new PointDialog();
  m_pointDialog->setHideRawValues(true);

  ui.vboxLayout->insertWidget(0, m_pointDialog);

  connect(m_pointDialog, SIGNAL(directionChanged(int, Vec)),
	  this, SIGNAL(directionChanged(int, Vec)));
  connect(m_pointDialog, SIGNAL(pointChanged(int, Vec)),
	  this, SLOT(pointChanged(int, Vec)));
  connect(m_pointDialog, SIGNAL(showPoints(bool)),
	  this, SLOT(showPoints(bool)));
  connect(m_pointDialog, SIGNAL(pointNumber(int)),
	  this, SLOT(pointNumber(int)));

  m_pointDialog->hide();
  ui.groupBox1->hide();
  ui.groupBox2->hide();
}

PathDialog::~PathDialog()
{
  clear();
  delete m_pointDialog;
}

void
PathDialog::clear()
{
  m_pointDialog->clear();
  m_points.clear();
  m_radX.clear();
  m_radY.clear();
  m_angle.clear();

  m_pointDialog->hide();
  ui.groupBox1->hide();
  ui.groupBox2->hide();
}

void
PathDialog::setPathObject(PathObject po)
{
  m_showPoints = po.showPoints();

  m_points = po.points();

  if (m_points.count() > 0)
    {
      m_pointDialog->show();
      ui.groupBox1->show();
      ui.groupBox2->show();
    }
  else
    {
      clear();
      return;
    }

  m_radX = po.radX();
  m_radY = po.radY();
  m_angle = po.angle();
  m_color = po.color();
  m_opacity = po.opacity();
  m_sections = po.sections();
  m_segments = po.segments();
  m_tube = po.tube();
  m_closed = po.closed();

  m_capType = po.capType();
  m_arrowDirection = po.arrowDirection();
  m_arrowForAll = po.arrowForAll();

  m_pointNumber = 0;
  fillInformation();
}

void
PathDialog::fillInformation()
{
  if (m_points.count() == 0)
    return;

  m_pointDialog->setPoints(m_points);
  m_pointDialog->setHideRawValues(true);

  m_sameForAll = false;
  ui.sameforall->setChecked(m_sameForAll);

  ui.sections->setValue(m_sections);
  ui.divisions->setValue(m_segments);
  ui.opacity->setValue(m_opacity);
  ui.radx->setValue(m_radX[m_pointNumber]);
  ui.rady->setValue(m_radY[m_pointNumber]);
  ui.angle->setValue(m_angle[m_pointNumber]);
  ui.closed->setChecked(m_closed);
  ui.tube->setChecked(m_tube);

  if (m_capType == PathObject::FLAT)
    ui.captype->setCurrentIndex(0);
  else if (m_capType == PathObject::ROUND)
    ui.captype->setCurrentIndex(1);
  else
    ui.captype->setCurrentIndex(2);

  if (m_capType == PathObject::ARROW)
    ui.arrow->show();
  else
    ui.arrow->hide();

  ui.arrowdirection->setChecked(m_arrowDirection);
  ui.arrowforall->setChecked(m_arrowForAll);
}

void
PathDialog::pointNumber(int idx)
{
  if (m_points.count() == 0)
    return;

  m_pointNumber = idx;
  ui.radx->setValue(m_radX[m_pointNumber]);
  ui.rady->setValue(m_radY[m_pointNumber]);
  ui.angle->setValue(m_angle[m_pointNumber]);
}

void
PathDialog::on_radx_valueChanged(double d)
{
  if (m_points.count() == 0)
    return;

  if (m_sameForAll)
    {
      for(int i=0; i<m_radX.count(); i++)
	m_radX[i] = d;
    }
  else
    m_radX[m_pointNumber] = d;
  updatePathObject();
}
void
PathDialog::on_rady_valueChanged(double d)
{
  if (m_points.count() == 0)
    return;

  if (m_sameForAll)
    {
      for(int i=0; i<m_radY.count(); i++)
	m_radY[i] = d;
    }
  else
    m_radY[m_pointNumber] = d;
  updatePathObject();
}
void
PathDialog::on_angle_valueChanged(double d)
{
  if (m_points.count() == 0)
    return;

  if (m_sameForAll)
    {
      for(int i=0; i<m_angle.count(); i++)
	m_angle[i] = d;
    }
  else
    m_angle[m_pointNumber] = d;
  updatePathObject();
}

void
PathDialog::on_sameforall_clicked(bool flag)
{
  m_sameForAll = flag;

  if (m_points.count() == 0)
    return;

  if (m_sameForAll)
    {      
      float d;

      d = m_radX[m_pointNumber];
      for(int i=0; i<m_radX.count(); i++)
	m_radX[i] = d;

      d = m_radY[m_pointNumber];
      for(int i=0; i<m_radY.count(); i++)
	m_radY[i] = d;

      d = m_angle[m_pointNumber];
      for(int i=0; i<m_angle.count(); i++)
	m_angle[i] = d;
    }

  updatePathObject();
}

void
PathDialog::on_color_clicked(bool flag)
{
  if (m_points.count() == 0)
    return;

  QColor dcolor = QColor::fromRgbF(m_color.x,
				   m_color.y,
				   m_color.z);
  QColor color = DColorDialog::getColor(dcolor);
  if (color.isValid())
    {
      float r = color.redF();
      float g = color.greenF();
      float b = color.blueF();
      m_color = Vec(r,g,b);
    }
  updatePathObject();
}

void
PathDialog::updatePathObject()
{
  if (m_points.count() == 0)
    return;

  m_sections = ui.sections->value();
  m_opacity = ui.opacity->value();
  m_closed = ui.closed->isChecked();
  m_segments = ui.divisions->value();
  m_tube = ui.tube->isChecked();
  m_arrowDirection = ui.arrowdirection->isChecked();
  m_arrowForAll = ui.arrowforall->isChecked();

  PathObject po;

  po.setCapType(m_capType);
  po.setArrowForAll(m_arrowForAll);
  po.setArrowDirection(m_arrowDirection);
  po.setTube(m_tube);
  po.setClosed(m_closed);
  po.setSections(m_sections);
  po.setSegments(m_segments);
  po.setColor(m_color);
  po.setOpacity(m_opacity);
  po.setPoints(m_points);
  po.setRadX(m_radX);
  po.setRadY(m_radY);
  po.setAngle(m_angle);
  po.setShowPoints(m_showPoints);

  emit pathObjectChanged(po);
}

void
PathDialog::on_captype_currentIndexChanged(int idx)
{
  if (m_points.count() == 0)
    return;

  if (idx == 0)
    m_capType = PathObject::FLAT;
  else if (idx == 1)
    m_capType = PathObject::ROUND;
  else
    m_capType = PathObject::ARROW;

  if (idx == 2)
    ui.arrow->show();
  else
    ui.arrow->hide();

  updatePathObject();
}

void PathDialog::on_arrowdirection_clicked(bool a) { updatePathObject(); }
void PathDialog::on_arrowforall_clicked(bool a) { updatePathObject(); }
void PathDialog::on_divisions_valueChanged(int a) { updatePathObject(); }
void PathDialog::on_sections_valueChanged(int a) { updatePathObject(); }
void PathDialog::on_opacity_valueChanged(double a) { updatePathObject(); }
void PathDialog::on_closed_clicked(bool a) { updatePathObject(); }
void PathDialog::on_spline_clicked(bool a) { updatePathObject(); }
void PathDialog::on_tube_clicked(bool a) { updatePathObject(); }


void
PathDialog::pointChanged(int i, Vec v)
{
  if (m_points.count() == 0)
    return;

  m_points[i] = v;
  updatePathObject();
}
void
PathDialog::showPoints(bool flag)
{
  if (m_points.count() == 0)
    return;

  m_showPoints = flag;
  updatePathObject();
}

void
PathDialog::on_remove_pressed()
{
  if (m_points.count() == 0)
    return;

  if (m_points.count() <= 2)
    {
      emit showMessage("Sorry cannot remove current point. Must have atleast 2 points in a path", true);
      return;
    }

  QList<Vec>::iterator itp = m_points.begin() + m_pointNumber;
  m_points.erase(itp);

  QList<float>::iterator itf = m_radX.begin() + m_pointNumber;
  m_radX.erase(itf);

  itf = m_radY.begin() + m_pointNumber;
  m_radY.erase(itf);

  itf = m_angle.begin() + m_pointNumber;
  m_angle.erase(itf);

  m_pointNumber = qMin((int)m_pointNumber, m_points.count()-1);

  fillInformation();

  updatePathObject();
}

void
PathDialog::on_insertafter_pressed()
{
  if (m_points.count() == 0)
    return;

  int npts = m_points.count();
  if (m_pointNumber == npts-1)
    {
      Vec v = m_points[npts-1]-m_points[npts-2];
      v += m_points[npts-1];
      m_points.append(v);
      m_radX.append(m_radX[npts-1]);
      m_radY.append(m_radY[npts-1]);
      m_angle.append(m_angle[npts-1]);
    }
  else
    {
      Vec v = (m_points[m_pointNumber]+m_points[m_pointNumber+1])/2;
      m_points.insert(m_pointNumber+1, v);

      float f;
      f = (m_radX[m_pointNumber]+m_radX[m_pointNumber+1])/2;
      m_radX.insert(m_pointNumber+1, f);

      f = (m_radY[m_pointNumber]+m_radY[m_pointNumber+1])/2;
      m_radY.insert(m_pointNumber+1, f);

      f = (m_angle[m_pointNumber]+m_angle[m_pointNumber+1])/2;
      m_angle.insert(m_pointNumber+1, f);
    }

  fillInformation();

  updatePathObject();
}

void
PathDialog::on_insertbefore_pressed()
{
  if (m_points.count() == 0)
    return;

  if (m_pointNumber == 0)
    {
      Vec v = m_points[0]-m_points[1];
      v += m_points[0];

      m_points.insert(0, v);
      m_radX.insert(0, m_radX[0]);
      m_radY.insert(0, m_radY[0]);
      m_angle.insert(0, m_angle[0]);
    }
  else
    {
      Vec v = (m_points[m_pointNumber]+m_points[m_pointNumber-1])/2;
      m_points.insert(m_pointNumber, v);
  
      float f;
      f = (m_radX[m_pointNumber]+m_radX[m_pointNumber-1])/2;
      m_radX.insert(m_pointNumber, f);
  
      f = (m_radY[m_pointNumber]+m_radY[m_pointNumber-1])/2;
      m_radY.insert(m_pointNumber, f);
  
      f = (m_angle[m_pointNumber]+m_angle[m_pointNumber-1])/2;
      m_angle.insert(m_pointNumber, f);
    }

  fillInformation();

  updatePathObject();
}
